﻿//*********************************************************************
//
//  文件名：AuthorizeFilter
//
//  作者： LW
//
//  作用：
//
//  日期：2015/9/8 16:23:08
//
//*********************************************************************
using Framework.Common;
using Framework.Common.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Security.Claims;
using System.Threading;
using System.Web;
using System.Web.Http;
using YouTravel.DomainModels;
using YouTravel.Framework.Const;
using YouTravel.Framework.Enums;
using YouTravel.Framework.ResourceMessage;
using YouTravel.ViewModels;

namespace Application.WebAPI.Filter
{
    /// <summary>
    /// AuthorizeFilter
    /// 页面访问
    /// 权限验证
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeFilter : AuthorizeAttribute
    {
        /// <summary>
        /// 返回值为false时执行
        /// </summary>
        /// <param name="actionContext"></param>
        protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            base.HandleUnauthorizedRequest(actionContext);
            if (actionContext.Response.StatusCode == HttpStatusCode.Unauthorized)
            {
                throw new AuthorizeException("用户未认证，请求失败");
                //var response = CommonGlobal.getInstance().ReturnJson((int)HttpStatusCode.Unauthorized, );
                //actionContext.Response = actionContext.Request.CreateResponse<string>(HttpStatusCode.Unauthorized, response, JsonMediaTypeFormatter.DefaultMediaType);
                //actionContext.Response = response;
            }
        }

        protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            //允许匿名访问
            if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0)
                return true;

            //验证是否认证通过
            ClaimsPrincipal principal = Thread.CurrentPrincipal as ClaimsPrincipal;
            if (!principal.Identity.IsAuthenticated)
                return false;

            //当前用户ID
            string userId = principal.Claims.Where(c => c.Type == "sub").Single().Value;
            if (string.IsNullOrWhiteSpace(userId))
                return false;

            #region 当前登录用户状态
            var user = RedisHelp.GetLoginUserCacheNotNull(int.Parse(userId));
            if (user == null)
                return false;
            if (user.Status != UserStatus.Normal)
                throw new BusinessException("用户状态异常");
            if ((int)user.Type != 0)
            {
                //机构、分社
                if (user.Type == UserType.Company || user.Type == UserType.Branch)
                { if (!user.Branch.Status) { throw new BusinessException(BusinessResourceMessage.LoginFailFrozenB); } }

                //专线
                if (user.Type == UserType.SpecialLine)
                { if (user.Special.Status != SpecialStatus.Normal) { throw new BusinessException(BusinessResourceMessage.LoginFailFrozenB); } }
            }
            #endregion

            #region 单点登录判断
            if (System.Configuration.ConfigurationManager.AppSettings["SingleSignOn"] == "1")
            {
                IEnumerable<string> iv = new List<string>();
                bool iflag = actionContext.Request.Headers.TryGetValues("identity", out iv);
                if (!iflag || iv.Count() <= 0)
                    return false;
                if (user.Token != iv.First())
                    throw new AccountLoginInOtherPlacesException("用户已在其他地方登录，请重新登录");
            }
            #endregion

            //请求URL
            string url = actionContext.Request.RequestUri.AbsolutePath.ToLower();

            CheckAuth(url, user);

            return base.IsAuthorized(actionContext);

            //string controllerName = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            //string actionName = actionContext.ActionDescriptor.ActionName;
            //string fullRequestUrl = controllerName + "/" + actionName;
        }

        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            base.OnAuthorization(actionContext);
        }

        private void CheckAuth(string requestUrl, UserViewModel user)
        {
            if (BusinessConst.PermissionFilter.Contains(requestUrl))
            {
                return;
            }
            if ((int)user.Type != 0)
            {
                requestUrl = requestUrl + ",";
                var tmp = user.Menus.Where(c => c.Url.Contains(requestUrl)).ToList();
                if (!tmp.Any())
                    throw new DataOperationPermissions("用户无权限访问该资源，请求失败");
            }
        }
    }
}